﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
using System.Web;

namespace ProjBackEnd.Models
{
    /// <summary>
    /// 当指定字段的值为指定值时，当前操作对象为必填项
    /// </summary>
    [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
    public class RequiredConditionalAttribute : ValidationAttribute
    {
        private const string DefaultErrorMessageFormatString = "【{0}】字段是必须的";
        private readonly string strFieldNameTarget;
        private readonly string strFeildValueTarget;

        public string FieldName { get { return strFieldNameTarget; } }
        public string FieldValue { get { return strFeildValueTarget; } }

        public RequiredConditionalAttribute(string _strFieldNameTarget, string _strFeildValueTarget)
        {
            ErrorMessage = DefaultErrorMessageFormatString;
            strFieldNameTarget = _strFieldNameTarget;
            strFeildValueTarget = _strFeildValueTarget;
        }

        protected override ValidationResult IsValid(object item, ValidationContext validationContext)
        {
            if (validationContext == null) return ValidationResult.Success;
            PropertyInfo property = validationContext.ObjectInstance.GetType().GetProperty(strFieldNameTarget);
            object objPropertyValueSour = property.GetValue(validationContext.ObjectInstance, null);

            if (objPropertyValueSour != null)
            {
                string strItemValue = (item == null ? "" : item.ToString());
                if (strFeildValueTarget.ToUpper().Contains(objPropertyValueSour.ToString().ToUpper()) && string.IsNullOrEmpty(strItemValue))
                    return new ValidationResult(string.Format(ErrorMessageString, validationContext.DisplayName));
            }

            return ValidationResult.Success;
        }
    }

    /// <summary>
    /// 当前操作对象值必须小于（等于）指定字段的值（仅限Decimal类型比较）
    /// </summary>
    [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
    public class CompareDecimalValueAttribute : ValidationAttribute
    {
        private const string DefaultErrorMessageFormatString = "【{0}】的值不能大于【{1}】的值";
        private readonly string strFieldNameTarget;
        private readonly bool isContainEquals;

        /// <summary>
        /// 当前操作对象值必须小于（等于）指定字段的值（仅限Decimal类型比较）
        /// </summary>
        /// <param name="_strFieldNameTarget">参与比较的字段名</param>
        /// <param name="_isContainEquals">比较行为是否包含等于</param>
        public CompareDecimalValueAttribute(string _strFieldNameTarget, bool _isContainEquals = true)
        {
            ErrorMessage = DefaultErrorMessageFormatString;
            strFieldNameTarget = _strFieldNameTarget;
            isContainEquals = _isContainEquals;
        }
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (validationContext == null) return ValidationResult.Success;
            PropertyInfo property = validationContext.ObjectInstance.GetType().GetProperty(strFieldNameTarget);
            string strTargetDisplayName = ((TypeDescriptor.GetProperties(validationContext.ObjectInstance.GetType()))[strFieldNameTarget].Attributes[typeof(DisplayAttribute)] as DisplayAttribute).Name;
            object objPropertyValueTarget = property.GetValue(validationContext.ObjectInstance, null);
            if (objPropertyValueTarget != null)
            {
                decimal decTarget; //特性参数中指定的字段值
                decimal decSour; //当前操作的字段值
                try
                {
                    decTarget = Convert.ToDecimal(objPropertyValueTarget);
                    decSour = Convert.ToDecimal(value);
                }
                catch { decTarget = decSour = 0; }
                if (isContainEquals && decSour <= decTarget) return ValidationResult.Success;
                if (!isContainEquals && decSour < decTarget) return ValidationResult.Success;

                return new ValidationResult(string.Format(ErrorMessage, validationContext.DisplayName, strTargetDisplayName));
            }
            return ValidationResult.Success;
        }

    }

}